﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;
using System.Collections;
using System.Windows.Controls;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Media.Imaging;
using MvvmTreeView.Converters;

namespace MvvmTreeView
{
    public class NodeImageAttribute : Attribute
    {
        public string ImagePath { get; set; }

        public NodeImageAttribute(string imagePath)
        {
            this.ImagePath = imagePath;
        }
    }

    public class ImageList
    {
        private ImageCollection collection;
        private Dictionary<string, List<ImageAvailableHandler>> loadHandlers;

        public ImageList()
        {
            collection = new ImageCollection();
            loadHandlers = new Dictionary<string, List<ImageAvailableHandler>>();

            collection.CollectionChanged += new NotifyCollectionChangedEventHandler(collection_CollectionChanged);
            collection.PropertyChanged += new PropertyChangedEventHandler(collection_PropertyChanged);
        }

        private void collection_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {

        }

        public Dictionary<string, List<ImageAvailableHandler>> ImageLoadHandlers
        {
            get 
            {
                return loadHandlers; 
            }
        }

        private void collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            
        }

        public ImageList(IContainer container)
        {
            collection = new ImageCollection();
        }

        public ImageList.ImageCollection Images 
        {
            get
            {
                return collection;
            }
        }

        public Size ImageSize { get; set; }
        public object Tag { get; set; }
        public Color TransparentColor { get; set; }

        public void Draw(/* todo */ object g, Point pt, int index)
        {
            throw new NotImplementedException();
        }

        public void Draw(/* todo */ object g, int x, int y, int index)
        {
            throw new NotImplementedException();
        }

        public void Draw(/* todo */ object g, int x, int y, int width, int height, int index)
        {
            throw new NotImplementedException();
        }

        public override string ToString()
        {
            throw new NotImplementedException();
        }

        public class ImageCollection : IList, ICollection, IEnumerable, INotifyCollectionChanged, INotifyPropertyChanged
        {
            public event NotifyCollectionChangedEventHandler CollectionChanged;
            public event PropertyChangedEventHandler PropertyChanged;
            private Dictionary<ImageIndex, BitmapImage> images;

            private class ImageIndex
            {
                public int Index { get; set; }
                public string Key { get; set; }
                public Color TransparentColor { get; set; }

                public ImageIndex()
                {
                }

                public ImageIndex(string key)
                {
                    this.Key = key;
                }

                public ImageIndex(int index)
                {
                    this.Index = index;
                }

                public ImageIndex(string key, Color transparentColor)
                {
                    this.Key = key;
                    this.TransparentColor = transparentColor;
                }

                public ImageIndex(int index, Color transparentColor)
                {
                    this.Index = index;
                    this.TransparentColor = transparentColor;
                }
            }

            public ImageCollection()
            {
                images = new Dictionary<ImageIndex, BitmapImage>();
            }

            public int Count
            {
                get
                {
                    return images.Count;
                }
            }

            public bool Empty
            {
                get
                {
                    return images.Count == 0;
                }
            }

            public bool IsReadOnly
            {
                get
                {
                    return false;
                }
            }

            public ICollection Keys
            {
                get
                {
                    return images.Keys;
                }
            }

            public BitmapImage this[int index]
            {
                get
                {
                    return images.First(k => ((ImageIndex)k.Key).Index == index).Value;
                }

                set
                {
                    images[new ImageIndex(index)] = value;

                    CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                    PropertyChanged(this, new PropertyChangedEventArgs("Count"));
                }
            }

            public BitmapImage this[string key]
            {
                get
                {
                    return images.First(k => ((ImageIndex) k.Key).Key == key).Value;
                }
            }

            public void Add(BitmapImage value)
            {
                images.Add(new ImageIndex(), value);

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
            }

            public void Add(string key, BitmapImage image)
            {
                images.Add(new ImageIndex(key), image);

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
            }

            public void Add(string key, BitmapImage value, Color transparentColor)
            {
                images[new ImageIndex(key, transparentColor)] = value;

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
            }

            public void Add(int index, BitmapImage value, Color transparentColor)
            {
                images[new ImageIndex(index, transparentColor)] = value;

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
            }

            public void Add(string key, byte[] value, Color transparentColor)
            {
                ByteArrayToBitMapConverter converter = new ByteArrayToBitMapConverter();
                BitmapImage image = (BitmapImage)converter.Convert(value, typeof(BitmapImage), null, null);

                images[new ImageIndex(key, transparentColor)] = image;

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
            }

            public void Add(int index, byte[] value, Color transparentColor)
            {
                ByteArrayToBitMapConverter converter = new ByteArrayToBitMapConverter();
                BitmapImage image = (BitmapImage)converter.Convert(value, typeof(BitmapImage), null, null);

                images[new ImageIndex(index, transparentColor)] = image;

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
            }

            public void AddRange(Image[] images)
            {
                throw new NotImplementedException();
            }

            public int AddStrip(BitmapImage value)
            {
                throw new NotImplementedException();
            }

            public void Clear()
            {
                images.Clear();

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
            }

            public bool Contains(BitmapImage image)
            {
                return images.ContainsValue(image);
            }

            public bool ContainsKey(string key)
            {
                return images.Any(k => ((ImageIndex)k.Key).Key == key);
            }

            public IEnumerator GetEnumerator()
            {
                return images.Values.GetEnumerator();
            }

            public int IndexOf(BitmapImage image)
            {
                return images.First(k => k.Value == image).Key.Index;
            }

            public int IndexOfKey(string key)
            {
                return images.First(k => ((ImageIndex)k.Key).Key == key).Key.Index;
            }

            public void Remove(BitmapImage image)
            {
                images.Remove(images.First(k => k.Value == image).Key);

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove));
                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
            }

            public void RemoveAt(int index)
            {
                images.Remove(images.First(k => k.Key.Index == index).Key);

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove));
                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
            }

            public void RemoveByKey(string key)
            {
                images.Remove(images.First(k => k.Key.Key == key).Key);

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove));
                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
            }

            public void SetKeyName(int index, string name)
            {
                images.First(k => k.Key.Index == index).Key.Key = name;

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace));
            }

            public int Add(object value)
            {
                this.Add((BitmapImage)value);

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                PropertyChanged(this, new PropertyChangedEventArgs("Count"));

                return this.IndexOf((BitmapImage)value);
            }

            public bool Contains(object value)
            {
                return this.Contains((BitmapImage)value);
            }

            public int IndexOf(object value)
            {
                return this.IndexOf((BitmapImage)value);
            }

            public void Insert(int index, object value)
            {
                images.Add(new ImageIndex(index), (BitmapImage) value);

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
            }

            public bool IsFixedSize
            {
                get 
                {
                    return false;
                }
            }

            public void Remove(object value)
            {
                this.Remove((BitmapImage)value);

                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove));
                PropertyChanged(this, new PropertyChangedEventArgs("Count"));
            }

            object IList.this[int index]
            {
                get
                {
                    return this[index];
                }
                set
                {
                    this[index] = (BitmapImage)value;

                    CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                    PropertyChanged(this, new PropertyChangedEventArgs("Count"));
                }
            }

            public void CopyTo(Array array, int index)
            {
                throw new NotImplementedException();
            }

            public bool IsSynchronized
            {
                get { throw new NotImplementedException(); }
            }

            public object SyncRoot
            {
                get { throw new NotImplementedException(); }
            }
        }
    }
}
